package info.batcloud.fanli.core.service.impl;

import com.ctospace.archit.common.pagination.Paging;
import info.batcloud.fanli.core.dto.AdvDTO;
import info.batcloud.fanli.core.dto.AdvSpaceDTO;
import info.batcloud.fanli.core.entity.AdvSpace;
import info.batcloud.fanli.core.entity.AdvSpaceItem;
import info.batcloud.fanli.core.exception.BizException;
import info.batcloud.fanli.core.repository.AdvRepository;
import info.batcloud.fanli.core.repository.AdvSpaceItemRepository;
import info.batcloud.fanli.core.repository.AdvSpaceRepository;
import info.batcloud.fanli.core.service.AdvService;
import info.batcloud.fanli.core.service.AdvSpaceItemService;
import info.batcloud.fanli.core.service.AdvSpaceService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.inject.Inject;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class AdvSpaceServiceImpl implements AdvSpaceService {

    @Inject
    private AdvSpaceRepository advSpaceRepository;

    @Inject
    private AdvSpaceItemRepository advSpaceItemRepository;

    @Inject
    private AdvService advService;

    @Inject
    private AdvRepository advRepository;

    @Inject
    private AdvSpaceService advSpaceService;

    @Inject
    private AdvSpaceItemService advSpaceItemService;

    @Override
    public void saveAdvSpace(AdvSpaceAddParam param) {
//        if (advSpaceRepository.countByCodeAndDeleted(param.getCode(), false) > 0) {
//            throw new BizException("广告位Code已经存在");
//        }
        AdvSpace as = new AdvSpace();
        as.setCreateTime(new Date());
        as.setCode(param.getCode());
        as.setName(param.getName());
        as.setDeleted(false);
        as.setValid(param.isValid());
        advSpaceRepository.save(as);
    }

    @Override
    public void updateAdvSpace(AdvSpaceUpdateParam param) {
//        if (advSpaceRepository.countByCodeAndDeletedAndIdIsNot(param.getCode(), false, param.getId()) > 0) {
//            throw new BizException("广告位Code已经存在");
//        }
        AdvSpace as = advSpaceRepository.findOne(param.getId());
        as.setCode(param.getCode());
        as.setName(param.getName());
        as.setDeleted(false);
        as.setValid(param.isValid());
        advSpaceRepository.save(as);
    }

    @Override
    public void validById(long id) {
        AdvSpace as = advSpaceRepository.findOne(id);
        as.setValid(true);
        advSpaceRepository.save(as);
    }

    @Override
    public void invalidById(long id) {
        AdvSpace as = advSpaceRepository.findOne(id);
        as.setValid(false);
        advSpaceRepository.save(as);
    }

    @Override
    public void deleteById(long id) {
        AdvSpace as = advSpaceRepository.findOne(id);
        as.setDeleted(true);
        advSpaceRepository.save(as);
    }

    @Override
    public AdvSpaceDTO findByAdvCode(String advCode) {
        AdvSpace advSpace = advSpaceRepository.findByCodeAndDeleted(advCode, false);
        if (advSpace == null) {
            return null;
        }
        return toBO(advSpace);
    }

    @Override
    public Paging<AdvSpaceDTO> search(SearchParam param) {
        Specification<AdvSpace> specification = (root, query, cb) -> {
            Predicate predicate = cb.conjunction();
            List<Expression<Boolean>> expressions = predicate.getExpressions();
            if (StringUtils.isNotEmpty(param.getName())) {
                expressions.add(cb.like(root.get("name"), "%" + param.getName() + "%"));
            }
            if (param.getValid() != null) {
                expressions.add(cb.equal(root.get("valid"), param.getValid()));
            }
            expressions.add(cb.equal(root.get("deleted"), false));
            return predicate;
        };
        Sort sort = new Sort(Sort.Direction.DESC, "id");
        Pageable pageable = new PageRequest(param.getPage() - 1,
                param.getPageSize(), sort);
        Page<AdvSpace> page = advSpaceRepository.findAll(specification, pageable);
        List<AdvSpaceDTO> dtoList = page.getContent().stream().map(a -> toBO(a)).collect(Collectors.toList());
        return Paging.of(dtoList, Long.valueOf(page.getTotalElements()).intValue(),
                param.getPage(), param.getPageSize());
    }

    @Override
    public List<AdvSpaceDTO> findList() {
        return advSpaceRepository.findByDeletedFalse().stream().map(a -> toBO(a)).collect(Collectors.toList());
    }

    @Override
    public List<AdvDTO> advListByAdvSpaceId(long advSpaceId) {
        List<AdvSpaceItem> advSpaceItems = advSpaceItemRepository.findByAdvSpaceId(advSpaceId);
        List<Long> advIds = advSpaceItems.stream().map(asi -> asi.getAdvId()).collect(Collectors.toList());
        return advService.findValidByIds(advIds);
    }

    @Override
    public List<AdvDTO> advListByAdvSpaceCode(String advCode) {
        AdvSpaceDTO advSpaceDTO = advSpaceService.findByAdvCode(advCode);
        if (advSpaceDTO == null) {
            return new ArrayList<>();
        }
        return advSpaceItemService.findByAdvSpaceId(advSpaceDTO.getId()).stream().map(asi -> asi.getAdv()).collect(Collectors.toList());
    }

    private AdvSpaceDTO toBO(AdvSpace adv) {
        AdvSpaceDTO bo = new AdvSpaceDTO();
        BeanUtils.copyProperties(adv, bo);
        return bo;
    }
}
